package exportSystem.Result;

import gameEngine.agents.teamMateModel.TeamMateModel;

import java.util.ArrayList;
import java.util.LinkedHashMap;
/**
 * this result is in the form of {@link ArrayList} of {@link ArrayList} of type double
 * where each {@link ArrayList} describes the competence an epsilon of agents in the 
 * Agent {@link TeamMateModel}
 * 
 * the meta data holds 2 fields one is competence and the other is epsilon
 * where each field holds total number of agents so when we format
 * we will know what field type we just got from the {@link ArrayList} 
 * 
 * @author alon
 *
 */
public class MetricResult implements Result{
	
	int teamMatesNumber;	
	ResultMetaData MetaData; 
	ArrayList<ArrayList<Double>> matrix;
	int totalSums=1;
	//Accuracy
	double compAccuracy;
	double epsAccuracy;
	
	public MetricResult(int teamMatesNum){
		this.teamMatesNumber=teamMatesNum;
		MetaData=new ResultMetaData(){
			public LinkedHashMap<String, Integer> getMetaData() {
				LinkedHashMap<String, Integer> metaData=new LinkedHashMap<String, Integer>();
				metaData.put("competence", teamMatesNumber);
				metaData.put("Egreedy", teamMatesNumber);
				return metaData;
			}		
		};
		
	}
	
	
	/**
	 * return an instance of the Matrix  
	 * @return {@link ArrayList} of {@link ArrayList} of double
	 */
	public ArrayList<ArrayList<Double>> getMatrix(){
		return matrix;
	}
	
	public void addMetric(ArrayList<Double> metric){
		if(matrix==null)
			matrix=new ArrayList<ArrayList<Double>>();
		matrix.add(metric);
	}

	public void sumMatrix(Result result){
		ArrayList<ArrayList<Double>> addedMatrix=result.getMetric();
		ArrayList<ArrayList<Double>> sumMatrix=new ArrayList<ArrayList<Double>>(); 
		for(int i=0;i<addedMatrix.size();i++){
			ArrayList<Double> sum=new ArrayList<Double>();
			for(int j=0;j<addedMatrix.get(i).size();j++){
				if(matrix==null){	
					sum.add(addedMatrix.get(i).get(j));
				}else{
					//if out of bound then hasent been created due to agent stopping the game previously
					try{
					sum.add(((matrix.get(i).get(j)*totalSums)+addedMatrix.get(i).get(j))/(totalSums+1));
				
					}catch (IndexOutOfBoundsException e) {
						sum.add(addedMatrix.get(i).get(j));
					}
				}
			}
			sumMatrix.add(sum);
		}
		matrix=sumMatrix;
		//count actes
		totalSums++;
	}
	
	public ResultMetaData getMetaData() {
		return MetaData;
	}

	public ArrayList<ArrayList<Double>> getMetric() {
		return matrix;
	}
	
	public void addCompAccurecy(double ac){
		this.compAccuracy+=ac;
	}
	
	public void addEpsAccuracy(double ac){
		this.epsAccuracy+=ac;
	}
	
	public double getCompAccuracy(){
		return compAccuracy/(totalSums-1);
	}
	
	public double getEpsAccuracy(){
		return epsAccuracy/(totalSums-1);
	}
}
